import { FormattedKlineData } from '../../services/market-data.service';
import { IndicatorsService } from '../../services/indicators.service';
import { TAKlineData } from '../../types/indicator.types';
import { BaseStrategy, BaseStrategyConfig, PositionState, TradeSignal, TradeOrder } from '../strategy.interface';

/**
 * MomentumTrackingStrategy 的特定配置接口
 */
export interface MomentumTrackingStrategyConfig extends BaseStrategyConfig {
  // EMA配置
  fastEmaPeriod: number;
  slowEmaPeriod: number;
  // RSI配置
  rsiPeriod: number;
  rsiUpperThreshold: number;
  rsiLowerThreshold: number;
  // 成交量配置
  volumeMaPeriod: number;
  volumeThreshold: number;
  // ATR配置
  atrPeriod: number;
  atrThreshold: number;
  // 止盈止损率
  longStopLossRate: number;
  shortStopLossRate: number;
  takeProfitRate: number;
}

/**
 * 动量追踪策略
 */
export class MomentumTrackingStrategy extends BaseStrategy {
  public name: string;
  public readonly warmupPeriod: number;

  private readonly config: MomentumTrackingStrategyConfig;

  // 指标数据
  private fastEmaValues: Map<number, number> = new Map();
  private slowEmaValues: Map<number, number> = new Map();
  private rsiValues: Map<number, number> = new Map();
  private atrValues: Map<number, number> = new Map();
  private volumeMaValues: Map<number, number> = new Map();

  private prevFastEma: number | null = null;
  private prevSlowEma: number | null = null;

  constructor(config: MomentumTrackingStrategyConfig) {
    super(config);
    this.config = config;

    const mode = this.accountType === 'spot' ? 'Spot' : 'Contract';
    this.name = `Momentum Tracking [${mode}]`;
    this.warmupPeriod = Math.max(config.slowEmaPeriod, config.rsiPeriod, config.atrPeriod, config.volumeMaPeriod) + 5;
    console.log(`Strategy created: ${this.name}. Requires ${this.warmupPeriod} warm-up periods.`);
  }

  public async initialize(data: FormattedKlineData[]): Promise<void> {
    console.log(`Calculating indicators for ${this.name}...`);
    const indicatorsService = new IndicatorsService();
    const taKlines: TAKlineData[] = data.map(k => ({
      timestamp: k.timestamp,
      open: k.open,
      high: k.high,
      low: k.low,
      close: k.close,
      volume: k.volume,
    }));

    // 计算所有需要的指标
    this.fastEmaValues = new Map(indicatorsService.calculateEMA(taKlines, { period: this.config.fastEmaPeriod }).map(r => [Number(r.timestamp), r.value]));
    this.slowEmaValues = new Map(indicatorsService.calculateEMA(taKlines, { period: this.config.slowEmaPeriod }).map(r => [Number(r.timestamp), r.value]));
    this.rsiValues = new Map(indicatorsService.calculateRSI(taKlines, { period: this.config.rsiPeriod }).map(r => [Number(r.timestamp), r.value]));
    this.atrValues = new Map(indicatorsService.calculateATR(taKlines, { period: this.config.atrPeriod }).map(r => [Number(r.timestamp), r.value]));

    // 计算成交量均线
    const volumeMaResults = indicatorsService.calculateSMA(taKlines.map(k => ({ ...k, close: k.volume })), { period: this.config.volumeMaPeriod });
    this.volumeMaValues = new Map(volumeMaResults.map(r => [Number(r.timestamp), r.value]));

    console.log(`Indicators calculated.`);
  }

  public update(kline: FormattedKlineData): TradeOrder {
    // 1. 优先检查止盈止损
    const takeProfitSignal = this.checkTakeProfit(kline);
    if (takeProfitSignal.signal !== TradeSignal.HOLD) return takeProfitSignal;

    const stopLossSignal = this.checkStopLoss(kline);
    if (stopLossSignal.signal !== TradeSignal.HOLD) return stopLossSignal;

    // 2. 获取当前周期的所有指标数据
    const fastEma = this.fastEmaValues.get(kline.timestamp);
    const slowEma = this.slowEmaValues.get(kline.timestamp);
    const rsi = this.rsiValues.get(kline.timestamp);
    const atr = this.atrValues.get(kline.timestamp);
    const volumeMa = this.volumeMaValues.get(kline.timestamp);

    if (fastEma === undefined || slowEma === undefined || rsi === undefined || atr === undefined || volumeMa === undefined || this.prevFastEma === null || this.prevSlowEma === null) {
      if (fastEma !== undefined) this.prevFastEma = fastEma;
      if (slowEma !== undefined) this.prevSlowEma = slowEma;
      return { signal: TradeSignal.HOLD };
    }

    // 3. 波动率过滤
    if (atr < kline.close * this.config.atrThreshold) {
      return { signal: TradeSignal.HOLD }; // 波动太小，不交易
    }

    // 4. 量能验证
    const isVolumeSpike = kline.volume > volumeMa * this.config.volumeThreshold;

    // 5. 定义交易条件
    const isGoldenCross = this.prevFastEma <= this.prevSlowEma && fastEma > slowEma;
    const isDeathCross = this.prevFastEma >= this.prevSlowEma && fastEma < slowEma;

    this.prevFastEma = fastEma;
    this.prevSlowEma = slowEma;

    // 6. 开仓逻辑
    if (this.accountType === 'contract') {
      // 开多仓条件
      if (isGoldenCross && rsi > this.config.rsiUpperThreshold && isVolumeSpike && this.contractState !== PositionState.LONG) {
        this.contractState = PositionState.LONG;
        this.entryPrice = kline.close;
        this.stopLossPrice = this.calcContractStopLossPrice(this.entryPrice, PositionState.LONG, this.config.longStopLossRate);
        this.takeProfitPrice = this.calcContractTakeProfitPrice(this.entryPrice, PositionState.LONG, this.config.takeProfitRate);
        return { signal: TradeSignal.OPEN_LONG };
      }
      // 开空仓条件
      if (isDeathCross && rsi < this.config.rsiLowerThreshold && isVolumeSpike && this.contractState !== PositionState.SHORT) {
        this.contractState = PositionState.SHORT;
        this.entryPrice = kline.close;
        this.stopLossPrice = this.calcContractStopLossPrice(this.entryPrice, PositionState.SHORT, this.config.shortStopLossRate);
        this.takeProfitPrice = this.calcContractTakeProfitPrice(this.entryPrice, PositionState.SHORT, this.config.takeProfitRate);
        return { signal: TradeSignal.OPEN_SHORT };
      }
    } else {
      // 现货开仓逻辑
      if (isGoldenCross && rsi > this.config.rsiUpperThreshold && isVolumeSpike && this.spotLastSignal !== TradeSignal.BUY) {
        this.spotLastSignal = TradeSignal.BUY;
        this.entryPrice = kline.close;
        this.stopLossPrice = this.entryPrice * (1 - this.config.longStopLossRate);
        this.takeProfitPrice = this.entryPrice * (1 + this.config.takeProfitRate);
        return { signal: TradeSignal.BUY };
      }
      // 现货平仓逻辑 (仅在持仓时检查死叉)
      if (isDeathCross && this.spotLastSignal === TradeSignal.BUY) {
        this.spotLastSignal = TradeSignal.SELL;
        this.entryPrice = null;
        this.stopLossPrice = null;
        this.takeProfitPrice = null;
        return { signal: TradeSignal.SELL };
      }
    }

    return { signal: TradeSignal.HOLD };
  }
}
